﻿using System;
using System.IO;
using System.Net;
using System.Linq;
using System.Text;
using System.Activities;
using System.Activities.Expressions;
using System.Activities.Presentation.PropertyEditing;
using System.Activities.Statements;
using System.Collections.Generic;
using System.ComponentModel;
using FTP = FTPSClient;

namespace Vision.Core.ActivityComponents.IO.Ftp
{
    /// <summary>
    /// 
    /// </summary>
    [System.ComponentModel.Designer(typeof(FtpConnectionDesigner))]
    public class FtpConnection : NativeActivity
    {
        /// <summary>
        /// 
        /// </summary>
        internal FTP.FTPSClient FtpClient { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Browsable(false)]
        [DefaultValue(null)]
        public Activity Body { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [DefaultValue("")]
        public InArgument<string> Url { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [DefaultValue("")]
        public InArgument<string> Username { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [DefaultValue("")]
        public InArgument<string> Password { get; set; }

		/// <summary>
		/// 
		/// </summary>
		[DefaultValue("")]
		public InArgument<int?> Timeout { get; set; }
                
        /// <summary>
        /// 
        /// </summary>        
        public FtpSSLMode SSLMode { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public FlowNode Exception { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public FtpConnection()
        {
            this.SSLMode = FtpSSLMode.None;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        protected override void Execute(NativeActivityContext context)
        {                                                               
            if (this.Body != null){
                NetworkCredential credentials = new NetworkCredential(context.GetValue(this.Username), context.GetValue(this.Password));
                this.FtpClient = new FTP.FTPSClient();
                this.FtpClient.Connect(context.GetValue(this.Url), credentials, this.MapESSLSupportMode(this.SSLMode), this.Timeout.Get(context));
				
                context.Properties.Add("5AED2CE1-FB3C-45B3-9CB7-3DC8CD5E4C56", this.FtpClient);
                context.ScheduleActivity(this.Body, this.OnChildActivityCompleted);
            }            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="completedInstance"></param>
        private void OnChildActivityCompleted(NativeActivityContext context, ActivityInstance completedInstance)
        {
            context.Properties.Remove("5AED2CE1-FB3C-45B3-9CB7-3DC8CD5E4C56");
            this.FtpClient.Dispose();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sslMode"></param>
        /// <returns></returns>
        private FTP.ESSLSupportMode MapESSLSupportMode(FtpSSLMode sslMode)
        {
            switch (sslMode){
                case FtpSSLMode.All:
                    return FTP.ESSLSupportMode.All;
                case FtpSSLMode.Implicit:
                    return FTP.ESSLSupportMode.Implicit;
                case FtpSSLMode.CredentialsRequested:
                    return FTP.ESSLSupportMode.CredentialsRequested;
                case FtpSSLMode.CredentialsRequired:
                    return FTP.ESSLSupportMode.CredentialsRequired;
                case FtpSSLMode.ControlChannelRequested:
                    return FTP.ESSLSupportMode.ControlChannelRequested;
                case FtpSSLMode.ControlChannelRequired:
                    return FTP.ESSLSupportMode.ControlChannelRequired;
                case FtpSSLMode.DataChannelRequested:
                    return FTP.ESSLSupportMode.DataChannelRequested;
                case FtpSSLMode.DataChannelRequired:
                    return FTP.ESSLSupportMode.DataChannelRequired;
                case FtpSSLMode.ControlAndDataChannelsRequested:
                    return FTP.ESSLSupportMode.ControlAndDataChannelsRequested;
                case FtpSSLMode.ControlAndDataChannelsRequired:
                    return FTP.ESSLSupportMode.ControlAndDataChannelsRequired;
                default:
                    return FTP.ESSLSupportMode.ClearText;
            }
        }
                
        /// <summary>
        /// 
        /// </summary>
        public enum FtpSSLMode
        {
            None,
            All,
            Implicit,
            CredentialsRequested,
            CredentialsRequired,
            ControlChannelRequested,
            ControlChannelRequired,
            DataChannelRequested,
            DataChannelRequired,
            ControlAndDataChannelsRequested,
            ControlAndDataChannelsRequired
        }        
    }
}
